REXX Health Check for monitoring spool usage. Basically this script checks two things: - If any job in Execution queue takes more than MAXSPLUSAGE % of spool space. - If any job that takes more than SPLUSAGE % of spool space is growing quickly. To be exact if its spool usage increased by INCRSPEED since the last check run. So interval in which you run this check influences if any jobs will trigger EXCEPTION condition. To successfully run this check you need: - Put REXX script in System REXX library concatenation (SYS1.SAXREXEC is the default library). - Confirm if its code was correctly copied. Script uses OR operator '!' X'4F' in Hexadecimal code. Depending on your terminal emulator it may be incorrectly copied. Use "HEX ON" command to check if OR operator has X'4F' code, if not use "C '!' X'4F' ALL" command. - Allocate SPLDATA & REXXOUT data sets (SYSU.SPOOLCK1.SPLDATA & SYSU.SPOOLCK1.REXXOUT by default). - Enable Terminal Monitor Program (TMP) - Add AXRRXWKD to authorized commands in IKJEFTxx & restart System REXX. - Ensure that Health Checker user has RACF access to following resources: SPLDATA data set(UPDATE) ; REXXOUT data set(UPDATE) ; CONSOLE profile of TSOAUTH class(READ) ; JES2.DISPLAY.* profile in OPERCMDS class(READ). - Activate HZSPRMxx definition. **************************************************************************************************** REXX CODE **************************************************************************************************** /* REXX */ SIGNAL ON SYNTAX SIGNAL ON ERROR SIGNAL ON FAILURE SIGNAL ON HALT /*********************************************************************/ /* */ /* SPOOLCK1 - REXX CHECKS IF SPOOL USAGE OF ANY JOB */ /* IS INCREASING TOO FAST */ /* */ /* PARAMETERS: */ /* MAXSPLUSAGE - IF ANY JOB USES MORE THAN THIS VALUE CHECK */ /* ENDS IN EXCEPTION */ /* SPLUSAGE - DEFINES SCOPE OF THE CHECK, ALL JOBS THAT USE */ /* MORE SPOOL THAT THIS VALUE ARE VERIFIED BY THE CHECK */ /* INCRSPEED - IF JOBS SPOOL USAGE INCREASED MORE THAN THIS VALUE */ /* BETWEEN CHECK RUNS, CHECK ENDS IN EXCEPTION */ /* SPLDATA - DATA SET NEEDED FOR STORING JOB DATA BETWEEN CHECK RUNS */ /* */ /*********************************************************************/ /*********************************************************************/ /* HEALTH CHECK START */ /*********************************************************************/ SAY "CHECK RUN AT: "DATE()", "TIME() HZSLSTRT_RC = HZSLSTRT() IF HZSLSTRT_RC <> 0 THEN DO IF HZS_PQE_DEBUG = 1 THEN DO SAY "HZSLSTRT RC" HZSLSTRT_RC SAY "HZSLSTRT RSN" HZSLSTRT_RSN SAY "HZSLSTRT SYSTEMDIAG" HZSLSTRT_SYSTEMDIAG END EXIT END /*********************************************************************/ /* INPUT PARAMTERS PROCESSING */ /*********************************************************************/ PARSE VAR HZS_PQE_PARMAREA MAXSPLUSAGE SPLUSAGE INCRSPEED SPLDATA . IF DATATYPE(MAXSPLUSAGE)<>"NUM" ! DATATYPE(SPLUSAGE)<>"NUM", ! DATATYPE(INCRSPEED)<>"NUM" ! SYSDSN("'"SPLDATA"'")<>"OK" THEN DO HZSLFMSG_REQUEST = "STOP" HZSLFMSG_REASON = "BADPARM" CALL TERMINATE "INPUT PARAMETERS INCORRECT" END SAY "MAXSPLUSAGE IS: "MAXSPLUSAGE SAY "SPLUSAGE IS: "SPLUSAGE SAY "INCRSPEED IS: "INCRSPEED SAY "OUTPUT DATA SET: "SPLDATA /*********************************************************************/ /* MAIN HEALTH CHECK LOGIC */ /*********************************************************************/ ADDRESS TSO "ALLOC FI(INDD) DA('"SPLDATA"') OLD REUSE" IF HZS_PQE_FUNCTION_CODE = "INITRUN" THEN DO TEMP.1="END" "EXECIO * DISKW INDD (STEM TEMP. FINIS)" SAY "INITRUN MODE, SPLDATA CLEARED BEFORE CHECK EXECUTION" END CALL CHECK_ENVIRONMENT CALL GET_JOBS_INFO CALL CHECK_IF_MAX_REACHED CALL READ_PREVIOUS_JOBS_INFO CALL COMPARE_JOBS CALL WRITE_CURRENT_JOBS CALL HZS_SUCCESS "CHECK ENDED SUCCESSFULLY" EXIT /*********************************************************************/ /* HZS EXCEPTION MESSAGE */ /*********************************************************************/ HZS_EXCEPTION: PARSE ARG MESSAGE HZSLFMSG_REQUEST='DIRECTMSG' HZSLFMSG_SEVERITY='SYSTEM' HZSLFMSG_REASON='CHECKEXCEPTION' HZSLFMSG_DIRECTMSG_ID='HZSUH002E' HZSLFMSG_DIRECTMSG_TEXT=MESSAGE SAY "CHECK EXCEPTION: "MESSAGE CALL TERMINATE MESSAGE RETURN /*********************************************************************/ /* HZS SUCCESS MESSAGE */ /*********************************************************************/ HZS_SUCCESS: PARSE ARG MESSAGE HZSLFMSG_REQUEST='DIRECTMSG' HZSLFMSG_REASON='CHECKINFO' HZSLFMSG_DIRECTMSG_ID='HZSUH001I' HZSLFMSG_DIRECTMSG_TEXT=MESSAGE SAY "CHECK SUCCESS: "MESSAGE CALL TERMINATE MESSAGE RETURN /*********************************************************************/ /* COMPARES JOBS FROM CURRENT AND PREVIOUS RUN IF ANY GROWS TOO FAST */ /*********************************************************************/ COMPARE_JOBS: RISKJOBS=":" DO I=1 TO JOBID.0 DO N=1 TO OJOBID.0 IF JOBID.I=OJOBID.N & (OPERCENT.N+INCRSPEED) ":" THEN DO CALL WRITE_CURRENT_JOBS CALL HZS_EXCEPTION "JOB INCREASES SPOOL TOO QUICKLY"RISKJOBS END RETURN /*********************************************************************/ /* CHECK IF ANY JOBS EXCEEDED MAX SPOOL USAGE ALLOWED */ /*********************************************************************/ CHECK_IF_MAX_REACHED: MAXES=":" DO I=1 TO PERCENT.0 IF PERCENT.I > MAXSPLUSAGE THEN DO MAXES=MAXES" "JOBNAME.I"("PERCENT.I"%)" END END IF MAXES <> ":" THEN DO CALL WRITE_CURRENT_JOBS CALL HZS_EXCEPTION "JOB EXCEEDED MAX SPOOL USAGE"MAXES END RETURN /*********************************************************************/ /* READS JOBS WITH HIGH SPOOL USAGE FROM PREVIOUS CHECK RUN */ /*********************************************************************/ READ_PREVIOUS_JOBS_INFO: "EXECIO * DISKR INDD (STEM PREVINFO. FINIS)" IF PREVINFO.1 = "END" THEN DO CALL WRITE_CURRENT_JOBS CALL HZS_SUCCESS "NO JOBS FROM PREVIOUS RUN, COMPARE NOT NEEDED" END DO I=1 TO PREVINFO.0 PARSE VAR PREVINFO.I OJOBID.I OJOBNAME.I OPERCENT.I . SAY OJOBID.I'' OJOBNAME.I'' OPERCENT.I END I=I-1 SAY I" JOBS READ FROM SPLDATA" OJOBID.0=I OJOBNAME.0=I OPERCENT.0=I RETURN /*********************************************************************/ /* WRITES JOBS WITH HIGH SPOOL USAGE FROM CURRENT RUN TO SPLDATA */ /*********************************************************************/ WRITE_CURRENT_JOBS: SAY JOBID.0" JOBS WRITTEN TO SPLDATA" DO I=1 TO JOBID.0 TEMP.I = JOBID.I'' JOBNAME.I'' PERCENT.I END "EXECIO * DISKW INDD (STEM TEMP. FINIS)" RETURN /*********************************************************************/ /* GETS INFO ABOUT JOBS WITH HIGH SPOOL USAGE */ /*********************************************************************/ GET_JOBS_INFO: ADDRESS CONSOLE PREFIX"DJQ,Q=XEQ,SPL=(%>"SPLUSAGE"),SPL=(%),L=Z" GMSG = GETMSG('CMD.',,,,2) IF CMD.0 < 1 THEN DO HZSLFMSG_REQUEST = "STOP" HZSLFMSG_REASON = "ERROR" CALL TERMINATE "PROBLEM DURING EXECUTION of '$DJQ' COMMAND" END IF POS("NO SELECTABLE ENTRIES",CMD.2) <> 0 THEN DO TEMP.1="END" "EXECIO * DISKW INDD (STEM TEMP. FINIS)" CALL HZS_SUCCESS "NO JOB USES MORE THAN "SPLUSAGE"% OF SPOOL" END N=0 DO I=1 TO CMD.0 P1=POS("JOB(",CMD.I) IF P1 <> 0 THEN DO N=N+1 JOBID.N = SUBSTR(CMD.I,P1-9,8) P2=POS(") ",CMD.I) JOBNAME.N = SUBSTR(CMD.I,P1+4,P2-(P1+4)) P3=POS("PERCENT=",CMD.I) PERCENT.N = SUBSTR(CMD.I,P3+8,6) SAY JOBID.N'' JOBNAME.N'' PERCENT.N END END SAY N" JOBS RETURNED BY JES2" JOBID.0=N JOBNAME.0=N PERCENT.0=N RETURN /*********************************************************************/ /* CHECKS IF JES2 IS USED ON THE SYSTEM AND READS ITS PREFIX */ /*********************************************************************/ CHECK_ENVIRONMENT: SYSTEM = MVSVAR(SYSNAME) "CONSPROF SOLDISPLAY(NO) SOLNUM(500)" "CONSOLE ACTIVATE,NAME(C1)" ADDRESS CONSOLE "D O" GMSG = GETMSG('CMD.',,,,2) IF CMD.0 < 1 THEN DO HZSLFMSG_REQUEST = "STOP" HZSLFMSG_REASON = "ERROR" CALL TERMINATE "PROBLEM DURING EXECUTION OF 'D O' COMMAND" END DO I=1 TO CMD.0 PARSE VAR CMD.I PREF TASK SYS . IF TASK="JES2" & SYS=SYSTEM THEN DO PREFIX=PREF RETURN END END HZSLFMSG_REQUEST = "STOP" HZSLFMSG_REASON = "ENVNA" CALL TERMINATE "NO JES2 DETECTED ON THE SYSTEM" RETURN /*********************************************************************/ /* HANDLED ERROR ROUTINE */ /*********************************************************************/ TERMINATE: PARSE ARG ERROR_MSG SAY ERROR_MSG "FREE FI(INDD)" "CONSOLE DEACTIVATE" HZSLFMSG_RC = HZSLFMSG() HZSLSTOP_RC = HZSLSTOP() IF HZS_PQE_DEBUG = 1 THEN DO SAY "HZSLSTOP RC" HZSLSTOP_RC SAY "HZSLSTOP RSN" HZSLSTOP_RSN SAY "HZSLSTOP SYSTEMDIAG" HZSLSTOP_SYSTEMDIAG END EXIT /*********************************************************************/ /* UNHANDLED ERROR ROUTINE */ /*********************************************************************/ SYNTAX: ERROR: FAILURE: HALT: SAY "AN ERROR HAS OCCURRED ON LINE: "SIGL SAY "ERROR LINE: "SOURCELINE(SIGL) SAY "RETURN CODE: "RC HZSLFMSG_REQUEST = "STOP" HZSLFMSG_REASON = "ERROR" CALL TERMINATE "ERROR TEXT: "ERRORTEXT(RC) EXIT **************************************************************************************************** HZSPRMxx Definition: **************************************************************************************************** ADDREP CHECK(USERCHK,SPOOL_USAGE_CHECK) EXEC(SPOOLCK1) REXXHLQ(SYSU) REXXTSO(YES) REXXIN(NO) MSGTBL(*NONE) USS(NO) VERBOSE(NO) SEVERITY(HIGH) INTERVAL(0:05) ACTIVE EINTERVAL(SYSTEM) DATE(20170720) PARM('5 0.2 0.1 SYSU.SPOOLCK1.SPLDATA') REASON('Check if any running job spool usage grows too quickly.')